package coreutil

import (
	"bytes"
	"crypto/aes"
	"crypto/cipher"
)

type aesCbcPK7 struct {
}

func pkcs7Padding(data []byte, blockSize int) []byte {
	//判断缺少几位长度。最少1，最多 blockSize
	padding := blockSize - len(data)%blockSize
	//补足位数。把切片[]byte{byte(padding)}复制padding个
	padText := bytes.Repeat([]byte{byte(padding)}, padding)
	return append(data, padText...)
}

// pkcs7UnPadding 填充的反向操作
func pkcs7UnPadding(data []byte) []byte {
	length := len(data)
	if length == 0 {
		return nil
	}
	//获取填充的个数
	unPadding := int(data[length-1])
	return data[:(length - unPadding)]
}
func (p *aesCbcPK7) Encrypt(plaintext []byte, key []byte, iv []byte) ([]byte, error) {
	block, err := aes.NewCipher(key)
	if err != nil {
		return nil, err
	}
	plaintext = pkcs7Padding(plaintext, block.BlockSize())
	ciphertext := make([]byte, len(plaintext))
	mode := cipher.NewCBCEncrypter(block, iv)
	mode.CryptBlocks(ciphertext, plaintext)

	return ciphertext, nil

}

func (p *aesCbcPK7) Decrypt(encrypted []byte, key []byte, iv []byte) ([]byte, error) {
	if key == nil || len(key) != 16 {
		return nil, nil
	}
	if iv != nil && len(iv) != 16 {
		return nil, nil
	}

	block, err := aes.NewCipher(key)
	if err != nil {
		return nil, err
	}

	blockMode := cipher.NewCBCDecrypter(block, iv[:aes.BlockSize])
	decrypted := make([]byte, len(encrypted))
	blockMode.CryptBlocks(decrypted, encrypted)
	decrypted = pkcs7UnPadding(decrypted)
	return decrypted, nil
}

var (
	AesCbcPK7 = &aesCbcPK7{}
)
